package com.grt.condify.parser;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.grt.condify.annotation.GroupBy;
import com.grt.condify.annotation.OrderType;
import com.grt.condify.annotation.SearchType;
import com.grt.condify.common.constant.CommonConstants;
import com.grt.condify.dto.BaseDTO;
import com.grt.condify.exception.CondifyException;
import com.grt.condify.reflect.ClassInfo;
import com.grt.condify.reflect.ReflexUtil;
import com.grt.condify.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@Slf4j
public class MybatisSearchParser {

    public static <T> IPage<T> buildPage(BaseDTO query) {
        return new Page<>(query.getPageNum(), query.getPageSize());
    }

    public static <T> QueryWrapper<T> buildQueryWrapper(BaseDTO query) throws CondifyException {

        return buildBaseQueryWrapper(query, new QueryWrapper<T>());
    }

    public static <T> QueryWrapper<T> buildBaseQueryWrapper(BaseDTO query, QueryWrapper<T> queryWrapper) throws CondifyException {

        //通过ClassInfo获取到具有指定注解的属性
        ClassInfo classInfo = ClassInfo.forName(query.getClass());

        List<Field> searchFields = classInfo.getFieldsByAnnotation(SearchType.class);
        if (searchFields != null) {
            for (Field searchField : searchFields) {
                buildSearch(query, queryWrapper, AnnotationUtils.findAnnotation(searchField, SearchType.class), searchField.getName());
            }
        }

        List<Field> orderFields = classInfo.getFieldsByAnnotation(OrderType.class);
        if (orderFields != null) {
            for (Field orderField : orderFields) {
                buildOrder(query, queryWrapper, AnnotationUtils.findAnnotation(orderField, OrderType.class), orderField.getName());
            }
        }

        List<Field> groupByFields = classInfo.getFieldsByAnnotation(GroupBy.class);
        if (groupByFields != null) {
            for (Field groudByField : groupByFields) {
                buildGroupBy(queryWrapper, Objects.requireNonNull(AnnotationUtils.findAnnotation(groudByField, GroupBy.class)), groudByField.getName());
            }
        }

        return queryWrapper;
    }

    private static void buildSearch(BaseDTO query, QueryWrapper<?> queryWrapper, SearchType searchType, String _fieldName) throws CondifyException {
        Object fieldValue = ReflexUtil.getFieldValueByName(_fieldName, query);
        if (null == fieldValue) {
            return;
        }

        if (fieldValue instanceof String) {
            if (StringUtil.isEmpty((String) fieldValue)) {
                return;
            }
        }

        if (null == searchType) {
            return;
        }


        switch (searchType.sfType()) {
            //普通检索条件，支持一个字段
            case CommonConstants.NORMAL_SEARCH_FILED_TYPE:
                buildNormalSearch(queryWrapper, searchType, _fieldName, fieldValue);
                break;
            //特殊检索条件，支持多个字段
            case CommonConstants.SPECIAL_SEARCH_FILED_TYPE:
                buildSpecialNormalSearch(queryWrapper, searchType, fieldValue);
                break;
        }

    }

    private static <T> void buildSpecialNormalSearch(QueryWrapper<T> queryWrapper,
                                                     SearchType searchType, Object fieldValue) throws CondifyException {
        String[] searchFields = searchType.searchFields();

        if (searchFields.length == 0) {
            throw new CondifyException("特殊检索字段必须定义searchFields");
        }
        queryWrapper.and(tQueryWrapper -> {
            for (String searchField : searchFields) {
                tQueryWrapper.or().like(searchField, fieldValue);
            }
        });

    }

    private static void buildNormalSearch(QueryWrapper<?> queryWrapper,
                                          SearchType searchType, String fieldName, Object fieldValue) {

        if (!StringUtil.isEmpty(searchType.searchField())) {
            fieldName = searchType.searchField();
        }

        switch (searchType.type()) {
            case EQ:
                queryWrapper.eq(fieldName, fieldValue);
                break;
            case LIKE:
                queryWrapper.like(fieldName, fieldValue);
                break;
            case GT:
                queryWrapper.gt(fieldName, fieldValue);
                break;
            case LT:
                queryWrapper.lt(fieldName, fieldValue);
                break;
            case GE:
                queryWrapper.ge(fieldName, fieldValue);
                break;
            case LE:
                queryWrapper.le(fieldName, fieldValue);
                break;
            case IN:
                queryWrapper.in(fieldName, StringUtil.getList((String) fieldValue, CommonConstants.SEPARATOR_COMMA));
                break;
            case NIN:
                queryWrapper.notIn(fieldName, StringUtil.getList((String) fieldValue, CommonConstants.SEPARATOR_COMMA));
                break;
            default:
                break;
        }
    }

    private static <T> void buildOrder(BaseDTO query, QueryWrapper<T> queryWrapper, OrderType orderType, String _fieldName) {
        if (orderType == null) {
            return;
        }
        String fieldName = _fieldName;

        if (StringUtil.isEmpty(orderType.orderFiled())) {
            //@OrderType(type = OrderTypeValue.DESC)
            //private String crTime;以这种模式添加的注解
            switch (orderType.type()) {
                case ASC:
                    queryWrapper.orderByAsc(fieldName);
                    break;
                case DESC:
                    queryWrapper.orderByDesc(fieldName);
                    break;
                default:
                    break;
            }
        } else {
            //@OrderType(orderFiled = "monthlyKPI")
            //private String monthlyKPIOrder = "desc";以这种模式添加的注解
            fieldName = orderType.orderFiled();

            Object fieldValue = ReflexUtil.getFieldValueByName(_fieldName, query);
            try {
                if (CommonConstants.ORDER_ASC.equalsIgnoreCase((String) fieldValue)) {
                    queryWrapper.orderByAsc(fieldName);
                }
                if (CommonConstants.ORDER_DESC.equalsIgnoreCase((String) fieldValue)) {
                    queryWrapper.orderByDesc(fieldName);
                }
            } catch (Exception e) {
                log.info("处理查询排序字段出错！" + e);
            }

        }


    }

    private static void buildGroupBy(QueryWrapper<?> queryWrapper, GroupBy groupBy, String _fieldName) {
        String[] groupByFields = groupBy.groupByFields();
        if (groupByFields.length != 0) {
            queryWrapper.groupBy(Arrays.asList(groupByFields));
        } else {
            queryWrapper.groupBy(_fieldName);
        }

    }

}
